package com.he.strategy.impl;

import cn.hutool.core.lang.Assert;
import com.he.constant.CommonConstant;
import com.he.exception.ServiceException;
import com.he.strategy.UploadStrategy;
import com.he.utils.FileUtils;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;

/**
 * @author He
 * @version 1.0
 * @Date 2023/9/13 19:52
 * @Desc 抽象通用上传逻辑
 */
@Service
public abstract class AbstractUploadStrategyImpl implements UploadStrategy {


    /**
     * 模板方法，定义了一般的文件上传的通用流程，
     * 但某些需要根据具体的上传策略来实现。
     * @param file 文件
     * @param path 上传路径
     * @return {@link String} 文件地址
     */
    @Override
    public String uploadFile(MultipartFile file, String path) {
        try {
            if (file.getSize() > CommonConstant.MAX_FILE_SIZE_BYTES) {
                throw new ServiceException("文件大小超过允许的限制");
            }
            String originalFilename = file.getOriginalFilename();
            //生成文件路径
            Assert.notNull(originalFilename, "文件名不能为空");
            String fileName = FileUtils.generateFilePath(originalFilename);
            // 判断文件是否已存在
            if (!exists(path + fileName)) {
                // 不存在则继续上传
                upload(path, fileName, file.getInputStream());
            }
            // 返回文件访问路径
            return getFileAccessUrl(path + fileName);
        } catch (Exception e) {
            e.printStackTrace();
            throw new ServiceException("文件上传失败");
        }
    }

    /**
     * 判断文件是否存在
     *
     * @param filePath 文件路径
     * @return {@link Boolean}
     */
    public abstract Boolean exists(String filePath);

    /**
     * 上传
     *
     * @param path        路径
     * @param fileName    文件名
     * @param inputStream 输入流
     * @throws IOException io异常
     */
    public abstract void upload(String path, String fileName, InputStream inputStream) throws IOException;

    /**
     * 获取文件访问url
     *
     * @param filePath 文件路径
     * @return {@link String} 文件url
     */
    public abstract String getFileAccessUrl(String filePath);
}
